////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "WNMemory/inc/WNMemory.h"
#include "WNMath/inc/WNSegment3.h"
#include "WNMath/inc/WNExtended.h"
#include "WNMath/inc/WNLine2.h"
#include "WNMath/inc/WNLine3.h"
#include "WNMath/inc/WNRay2.h"
#include "WNMath/inc/WNRay3.h"
#include "WNMath/inc/WNVector3.h"

using namespace WNMemory;
using namespace WNMath;

// Constructors ////////////////////////////////////////////////////////////////////////////////////

WNSegment3::WNSegment3() :
    start(0.0f, 0.0f, 0.0f),
    end(0.0f, 0.0f, 0.0f) {
}

WNSegment3::WNSegment3(const WN_FLOAT32* _f) :
    start(_f[0], _f[1], _f[2]),
    end(_f[3], _f[4], _f[5]) {
}

WNSegment3::WNSegment3(const WNPoint3& _start, const WNPoint3& _end) :
    start(_start),
    end(_end) {
}

// Operators ///////////////////////////////////////////////////////////////////////////////////////

WNSegment3 WNSegment3::operator + () const {
    return(*this);
}

WNSegment3 WNSegment3::operator - () const {
    return(WNSegment3(-start, -end));
}

WN_BOOL WNSegment3::operator == (const WNSegment3& _seg) const {
    return(0 == WNMemCmp(this, &_seg, sizeof(WNSegment3)));
}

WN_BOOL WNSegment3::operator != (const WNSegment3& _seg) const {
    return(0 != WNMemCmp(this, &_seg, sizeof(WNSegment3)));
}

// Members /////////////////////////////////////////////////////////////////////////////////////////

WN_VOID WNSegment3::Zero() {
    start.Zero();
    end.Zero();
}

WN_VOID WNSegment3::Set(const WN_FLOAT32* _f) {
    start.x = _f[0];
    start.y = _f[1];
    start.z = _f[2];

    end.x = _f[3];
    end.y = _f[4];
    end.z = _f[5];
}

WN_VOID WNSegment3::Set(const WNPoint3& _start, const WNPoint3& _end) {
    start = _start;
    end = _end;
}

WN_FLOAT32 WNSegment3::Length() const {
    return(WNDistance(start, end));
}

WN_FLOAT32 WNSegment3::LengthSquared() const {
    return(WNDistanceSquared(start, end));
}

WNVector3 WNSegment3::Direction() const {
    return(end - start);
}

WNLine2 WNSegment3::ToLine2() const {
    return(WNLine2(start.ToPoint2(), end.ToPoint2()));
}

WNLine3 WNSegment3::ToLine3() const {
    return(WNLine3(start, end));
}

WNRay2 WNSegment3::ToRay2() const {
    return(WNRay2(start.ToPoint2(), (end - start).ToVector2()));
}

WNRay3 WNSegment3::ToRay3() const {
    return(WNRay3(start, end - start));
}